package com.zhentao.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zhentao.pojo.User;
import com.zhentao.service.UserService;
import com.zhentao.service.FaceCompareService;
import com.zhentao.config.MinioConfig;

import com.zhentao.utils.JwtUtil;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 人脸认证控制器
 * 处理人脸登录和注册相关功能
 */
@RestController
@RequestMapping("/auth")
//@CrossOrigin(origins = "*")
public class FaceAuthController {

    private static final Logger logger = LoggerFactory.getLogger(FaceAuthController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private FaceCompareService faceCompareService;

    @Autowired
    private MinioConfig minioConfig;

    // JWT配置
    private static final long ACCESS_TOKEN_TTL_MS = 24 * 60 * 60 * 1000L; // 24小时
    private static final long REFRESH_TOKEN_TTL_MS = 7 * 24 * 60 * 60 * 1000L; // 7天

    /**
     * 测试接口 - 验证请求是否到达
     */
    @PostMapping("/test")
    public ResponseEntity<Map<String, Object>> test(@RequestBody(required = false) Map<String, Object> requestBody) {
        logger.info("收到测试请求");
        logger.info("请求体: {}", requestBody);

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", "测试接口调用成功");
        response.put("timestamp", System.currentTimeMillis());
        response.put("receivedData", requestBody);

        return ResponseEntity.ok(response);
    }

    /**
     * MinIO配置测试接口
     */
    @GetMapping("/minio-config")
    public ResponseEntity<Map<String, Object>> testMinioConfig() {
        logger.info("收到MinIO配置测试请求");

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", "MinIO配置信息");
        response.put("endpoint", minioConfig.getEndpoint());
        response.put("accessKey", minioConfig.getAccessKey());
        response.put("faceImagesBucket", minioConfig.getFaceImagesBucket());
        response.put("timestamp", System.currentTimeMillis());

        // 测试MinIO连接
        try {
            MinioClient client = createMinioClient();
            boolean bucketExists = client.bucketExists(
                io.minio.BucketExistsArgs.builder()
                    .bucket(minioConfig.getFaceImagesBucket())
                    .build()
            );
            response.put("bucketExists", bucketExists);
            response.put("connectionStatus", "成功");
        } catch (Exception e) {
            logger.error("MinIO连接测试失败", e);
            response.put("connectionStatus", "失败: " + e.getMessage());
            response.put("bucketExists", false);
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 人脸注册接口
     * 1. 上传人脸图片到MinIO
     * 2. 保存用户信息和人脸图片路径
     */
    @PostMapping("/face-register")
    public ResponseEntity<Map<String, Object>> faceRegister(
            @RequestParam(value = "email", required = false) String email,
            @RequestParam(value = "username", required = false) String username,
            @RequestParam(value = "password", required = false) String password,
            @RequestParam(value = "nickname", required = false) String nickname,
            @RequestParam(value = "faceImage", required = false) MultipartFile faceImage) {

        logger.info("收到人脸注册请求");
        logger.info("请求参数 - 邮箱: {}, 用户名: {}, 昵称: {}", email, username, nickname);
        logger.info("人脸图片 - 是否为空: {}, 大小: {}",
                   faceImage == null || faceImage.isEmpty(),
                   faceImage != null ? faceImage.getSize() : 0);

        Map<String, Object> response = new HashMap<>();

        try {
            // 1. 参数验证
            if (!StringUtils.hasText(email) || !StringUtils.hasText(username) || 
                !StringUtils.hasText(password) || !StringUtils.hasText(nickname)) {
                return buildErrorResponse("参数不完整", HttpStatus.BAD_REQUEST);
            }

            if (faceImage == null || faceImage.isEmpty()) {
                return buildErrorResponse("请上传人脸图片", HttpStatus.BAD_REQUEST);
            }

            // 2. 检查邮箱和用户名是否已存在
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getEmail, email).or().eq(User::getUsername, username);
            User existingUser = userService.getOne(queryWrapper);

            if (existingUser != null) {
                if (email.equals(existingUser.getEmail())) {
                    return buildErrorResponse("邮箱已被注册", HttpStatus.CONFLICT);
                }
                if (username.equals(existingUser.getUsername())) {
                    return buildErrorResponse("用户名已被使用", HttpStatus.CONFLICT);
                }
            }

            // 3. 上传人脸图片到MinIO
            String faceImagePath = uploadFaceImageToMinio(faceImage, username);
            if (faceImagePath == null) {
                return buildErrorResponse("人脸图片上传失败", HttpStatus.INTERNAL_SERVER_ERROR);
            }

            // 4. 创建用户记录
            User user = new User();
            user.setEmail(email);
            user.setUsername(username);
            user.setPassword(sha256(password));
            user.setNickname(nickname);
            user.setFaceImage(faceImagePath);
            user.setStatus(1); // 启用状态
            user.setEmailVerified(1); // 人脸注册默认邮箱已验证
            user.setSailorAuthStatus(0); // 未认证海员
            user.setCreateTime(new Date());
            user.setUpdateTime(new Date());

            boolean saved = userService.save(user);
            if (!saved) {
                return buildErrorResponse("用户注册失败", HttpStatus.INTERNAL_SERVER_ERROR);
            }

            // 5. 生成JWT令牌
            String accessToken = JwtUtil.generateJwt(user, ACCESS_TOKEN_TTL_MS);
            String refreshToken = JwtUtil.generateJwt(user, REFRESH_TOKEN_TTL_MS);

            // 6. 返回成功结果
            response.put("success", true);
            response.put("message", "人脸注册成功");
            response.put("accessToken", accessToken);
            response.put("refreshToken", refreshToken);
            response.put("userId", user.getId());
            response.put("username", user.getUsername());
            response.put("nickname", user.getNickname());

            logger.info("人脸注册成功，用户ID: {}, 用户名: {}", user.getId(), user.getUsername());
            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("人脸注册异常", e);
            return buildErrorResponse("注册失败: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 人脸登录接口
     * 1. 根据用户名查找用户
     * 2. 获取数据库中的人脸图片
     * 3. 调用人脸比对接口
     * 4. 相似度>0.9则登录成功
     */
    @PostMapping("/face-login")
    public ResponseEntity<Map<String, Object>> faceLogin(
            @RequestParam("username") String username,
            @RequestParam("faceImage") MultipartFile faceImage) {

        logger.info("收到人脸登录请求，用户名: {}", username);

        Map<String, Object> response = new HashMap<>();

        try {
            // 1. 参数验证
            if (!StringUtils.hasText(username)) {
                return buildErrorResponse("请输入用户名", HttpStatus.BAD_REQUEST);
            }

            if (faceImage == null || faceImage.isEmpty()) {
                return buildErrorResponse("请上传人脸图片", HttpStatus.BAD_REQUEST);
            }

            // 2. 查找用户
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getUsername, username).eq(User::getStatus, 1);
            User user = userService.getOne(queryWrapper);

            if (user == null) {
                // 临时注释掉用户不存在的错误响应
                // return buildErrorResponse("用户不存在或已被禁用", HttpStatus.NOT_FOUND);

                // 返回默认响应，避免前端报错
                response.put("success", false);
                response.put("message", "用户信息验证失败");
                return ResponseEntity.ok(response);
            }

            if (!StringUtils.hasText(user.getFaceImage())) {
                return buildErrorResponse("该用户未录入人脸信息", HttpStatus.BAD_REQUEST);
            }

            // 3. 上传当前人脸图片到临时位置
            String tempFaceImagePath = uploadTempFaceImage(faceImage, username);
            if (tempFaceImagePath == null) {
                return buildErrorResponse("人脸图片处理失败", HttpStatus.INTERNAL_SERVER_ERROR);
            }

            // 4. 调用人脸比对接口
            double similarity = compareFaces(user.getFaceImage(), tempFaceImagePath);
            
            logger.info("人脸比对结果，用户: {}, 相似度: {}", username, similarity);

            // 5. 判断是否登录成功（相似度>0.9）
            if (similarity > 0.9) {
                // 登录成功，生成JWT令牌
                String accessToken = JwtUtil.generateJwt(user, ACCESS_TOKEN_TTL_MS);
                String refreshToken = JwtUtil.generateJwt(user, REFRESH_TOKEN_TTL_MS);

                response.put("success", true);
                response.put("message", "人脸登录成功");
                response.put("accessToken", accessToken);
                response.put("refreshToken", refreshToken);
                response.put("userId", user.getId());
                response.put("username", user.getUsername());
                response.put("nickname", user.getNickname());
                response.put("similarity", similarity);

                logger.info("人脸登录成功，用户ID: {}, 相似度: {}", user.getId(), similarity);
                return ResponseEntity.ok(response);
            } else {
                // 登录失败
                response.put("success", false);
                response.put("message", "人脸验证失败，相似度不足");
                response.put("similarity", similarity);
                response.put("threshold", 0.9);

                logger.warn("人脸登录失败，用户: {}, 相似度: {} < 0.9", username, similarity);
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

        } catch (Exception e) {
            logger.error("人脸登录异常", e);
            return buildErrorResponse("登录失败: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 上传人脸图片到MinIO
     */
    private String uploadFaceImageToMinio(MultipartFile file, String username) {
        try {
            MinioClient minioClient = createMinioClient();

            // 生成唯一文件名
            String fileName = "face_" + username + "_" + System.currentTimeMillis() + ".jpg";
            String objectName = "faces/" + fileName;

            // 上传文件
            try (InputStream inputStream = file.getInputStream()) {
                minioClient.putObject(
                    PutObjectArgs.builder()
                        .bucket(minioConfig.getFaceImagesBucket())
                        .object(objectName)
                        .stream(inputStream, file.getSize(), -1)
                        .contentType("image/jpeg")
                        .build()
                );
            }

            // 返回文件访问路径
            String filePath = minioConfig.getEndpoint() + "/" + minioConfig.getFaceImagesBucket() + "/" + objectName;
            logger.info("人脸图片上传成功: {}", filePath);
            return filePath;

        } catch (Exception e) {
            logger.error("上传人脸图片到MinIO失败", e);
            return null;
        }
    }

    /**
     * 上传临时人脸图片用于比对
     */
    private String uploadTempFaceImage(MultipartFile file, String username) {
        try {
            MinioClient minioClient = createMinioClient();

            // 生成临时文件名
            String fileName = "temp_face_" + username + "_" + System.currentTimeMillis() + ".jpg";
            String objectName = "temp/" + fileName;

            // 上传文件
            try (InputStream inputStream = file.getInputStream()) {
                minioClient.putObject(
                    PutObjectArgs.builder()
                        .bucket(minioConfig.getFaceImagesBucket())
                        .object(objectName)
                        .stream(inputStream, file.getSize(), -1)
                        .contentType("image/jpeg")
                        .build()
                );
            }

            // 返回文件访问路径
            String filePath = minioConfig.getEndpoint() + "/" + minioConfig.getFaceImagesBucket() + "/" + objectName;
            logger.info("临时人脸图片上传成功: {}", filePath);
            return filePath;

        } catch (Exception e) {
            logger.error("上传临时人脸图片失败", e);
            return null;
        }
    }

    /**
     * 调用人脸比对接口
     */
    private double compareFaces(String image1Path, String image2Path) {
        try {
            logger.info("调用人脸比对接口，图片1: {}, 图片2: {}", image1Path, image2Path);

            // 调用人脸比对服务
            Map<String, Object> result = faceCompareService.compareFaces(image1Path, image2Path);

            if (result != null && result.containsKey("score")) {
                double score = ((Number) result.get("score")).doubleValue();
                logger.info("人脸比对成功，相似度: {}", score);
                return score;
            } else {
                logger.warn("人脸比对返回结果异常: {}", result);
                return 0.0;
            }

        } catch (Exception e) {
            logger.error("人脸比对失败", e);
            return 0.0;
        }
    }

    /**
     * 创建MinIO客户端
     */
    private MinioClient createMinioClient() {
        return MinioClient.builder()
                .endpoint(minioConfig.getEndpoint())
                .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                .build();
    }

    /**
     * SHA-256加密
     */
    private String sha256(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException("SHA-256加密失败", e);
        }
    }

    /**
     * 构建错误响应
     */
    private ResponseEntity<Map<String, Object>> buildErrorResponse(String message, HttpStatus status) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("message", message);
        return ResponseEntity.status(status).body(response);
    }
}
